﻿// ******************************************************************
// 项目名称 :WSPay
// 项目描述 :
// 文件名称 : PaymentService.cs
// 版  本 : v1.0.0.0
// 说  明 :  
// 作  者 : mengzhong
// 邮  箱 :coodream@live.com
// 命名空间 : WSPay.Core
// 创建时间 : 2017.04.20.15:38
// 更新时间 : 2017.04.20.15:38
// ******************************************************************
//  Copyright meng zhong  2017. All rights reserved.
// ******************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Transactions;
using Hangfire;
using Newtonsoft.Json;
using WSPay.Common;
using WSPay.Common.Data;
using WSPay.Common.Log;
using WSPay.Core.DTO;
using WSPay.Domain;

namespace WSPay.Application
{
    public class PaymentService: BaseService,IPaymentService
    {
        
        public PaymentService(IUnitOfWork unitOfWork) : base(unitOfWork)
        {
           
        }
        public WSBPayMessageDTO CreatePayment(PaymentDto dto)
        {
            if (ValidateSignPayment(dto) != true)
            {
                return WSBPayMessageDTO.Code1001;
            }
            using (TransactionScope scope = new TransactionScope())
            {
                var payment = new PaymentOrder()
                {
                    BuyOrderId = dto.BuyOrderId,
                    OrderInfo = dto.OrderInfo,
                    UserID = dto.PayerID,
                    State = PaymentState.Unpaid,
                    TotalPrice = dto.OrderMoney,
                    PayAmount = dto.OrderMoney,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    Remark = dto.Remark,
                    NoticeUrl = dto.NoticeUrl,
                    RuturnUrl = dto.ReturnUrl,
                    ClientID = dto.ClientID.ToString()
                };
                _unitOfWork.D<PaymentOrder>().Insert(payment);
                _unitOfWork.Commit();
                scope.Complete();
            }
            return WSBPayMessageDTO.Code0000;
        }

      
        public bool SuccessPay(int orderId, string noticeId,string alyAccount,string alyId)
        {
            var payorder = _unitOfWork.D<PaymentOrder>().GetById(orderId);
            payorder.NoticeSn = noticeId;
            payorder.State=PaymentState.Completed;
            payorder.AliPayAccount = alyAccount;
            payorder.AliPayId = alyId;
            var  jobId = BackgroundJob.Schedule(
            () => NoticePay(payorder.OrderId),TimeSpan.FromMilliseconds(10));
            payorder.JobId = jobId;
            _unitOfWork.Commit();
            return true;
        }
        public bool FailurePay(int orderId, string noticeId)
        {
            var payorder = _unitOfWork.D<PaymentOrder>().GetById(orderId);
            payorder.NoticeSn = noticeId;
            payorder.State = PaymentState.Failure;
            var jobId = BackgroundJob.Schedule(
            () => NoticePay(payorder.OrderId), TimeSpan.FromMilliseconds(10));
            payorder.JobId = jobId;
            _unitOfWork.Commit();
            return true;
        }  
       

        public PaymentOrder GetPaymentOrder(string orderId)
        {
            return _unitOfWork.D<PaymentOrder>().ReadQuery().FirstOrDefault(x => x.OrderId == orderId);
        }
        public PaymentOrder GetPaymentOrderBuyOrder(string orderId) {
            Guid gid;
            if (Guid.TryParse(orderId, out gid)) {
                orderId = gid.ToString();
            }
            return _unitOfWork.D<PaymentOrder>().ReadQuery().FirstOrDefault(x => x.BuyOrderId == orderId);
        }


        private bool ValidateSignPayment(PaymentDto paybilldto)
        {
            var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == paybilldto.ClientID);

            if (clientInfo == null) return false;

            var sp = "|";

            var signString = paybilldto.ClientID + sp +
                clientInfo.MD5Key + sp +
                paybilldto.BuyOrderId + sp +
                paybilldto.OrderInfo + sp +
                paybilldto.OrderMoney + sp +
                paybilldto.PayerID + sp +
                paybilldto.PayerName + sp +
                paybilldto.TradeDate.ToString("yyyy-MM-dd HH:mm:ss") + sp +
                paybilldto.Remark;

            var sign = signString.Hash();

            if (string.IsNullOrEmpty(paybilldto.Sign) || !paybilldto.Sign.ToUpper().Equals(sign))
            {
                return false;
            }

            return true;
        }

       
        /// <summary>
        /// 支付通知
        /// </summary>
        /// <param name="orderId"></param>
        public void NoticePay(string orderId)
        {
            try
            {
                var _httpClient = new HttpClient();
                var data = _unitOfWork.D<PaymentOrder>().Query().FirstOrDefault(x => x.OrderId == orderId);
                var guidClentID = Guid.Parse(data.ClientID);
                var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == guidClentID);

                if (clientInfo == null)
                {
                    throw  new ApplicationException("ClientID is null");
                }
                var sp = "|";
                var signString = data.ClientID + sp +
                                 clientInfo.MD5Key + sp +
                                 data.BuyOrderId + sp +
                                 data.OrderId + sp +
                                 data.State + sp +
                                 data.PayAmount.ToString("0.00") + sp +
                                 data.UserID + sp;

                var sign = signString.Hash();
                _httpClient.BaseAddress=new Uri(data.NoticeUrl);
                var content = new FormUrlEncodedContent(new Dictionary<string, string>()
                   {
                       {"OrderId", data.OrderId},//支付订单ID
                       {"PayerID", data.UserID.ToString()},//支付用户ID
                       {"BuyOrderId", data.BuyOrderId},//原始订单ID
                       {"ClientID", data.ClientID},
                       {"State", data.State==PaymentState.Completed?"success":"fail"},//支付状态
                       {"OrderMoney",data.PayAmount.ToString("0.00")},//订单金额
                       {"AliAcount", data.AliPayAccount},//支付宝账户
                       {"AliId", data.AliPayId},//支付宝ID
                       {"Sign", sign} 
                   });
                var response =_httpClient.PostAsync(data.NoticeUrl, content);
                NLogLogger nlog = new NLogLogger();
                nlog.Info("电商返回通知数据：" + response.Result.Content.ReadAsStringAsync().Result+"|"+sign+"----"+signString);
                string responseString = response.Result.Content.ReadAsStringAsync().Result;

                if (responseString != "success")//不成功继续通知
                {
                    BackgroundJob.Schedule(
                         () => NoticePay(data.OrderId), TimeSpan.FromMilliseconds(10));
                }
            }
            catch (Exception e)
            {
              throw new ApplicationException(e.Message);
            }
        }

        public string GetMd5Key(string clientId)
        {
            var guidClentID = Guid.Parse(clientId);
            var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == guidClentID);
            return clientInfo.MD5Key;
        }
    }
}